package com.luo.d3s.light.mybatis.ec.interfaces.web.config;

import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.datetime.DateFormatterRegistrar;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

/**
 * Jackson日期格式配置
 *
 * <ol>
 *     <li>请求体、响应体JSON可通过@JsonFormat(pattern="yyyy-MM-dd")注解覆盖默认配置</li>
 *     <li>请求参数、请求参数对象可通过@DateTimeFormat(pattern="yyyy-MM-dd")注解覆盖默认配置</li>
 * </ol>
 *
 * @author luohq
 * @date 2022-05-17 10:33
 */
@Configuration
@EnableConfigurationProperties({WebJacksonProps.class})
@ConditionalOnProperty(prefix = WebJacksonProps.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class WebJacksonConfiguration implements WebMvcConfigurer {

    /**
     * Web Jackson配置属性
     */
    private WebJacksonProps webJacksonProps;

    public WebJacksonConfiguration(WebJacksonProps webJacksonProps) {
        this.webJacksonProps = webJacksonProps;
    }

    /**
     * Json请求体、响应体 - 日期序列化配置
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> {
            //java.util.Date日期格式
            builder.simpleDateFormat(this.webJacksonProps.getDateFormat());

            //Java8+ java.time.*日期格式
            DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern(this.webJacksonProps.getLocalDateFormat())
                    .withZone(ZoneId.of(this.webJacksonProps.getTimeZone()));
            DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern(this.webJacksonProps.getLocalDateTimeFormat())
                    .withZone(ZoneId.of(this.webJacksonProps.getTimeZone()));
            builder.serializers(new LocalDateSerializer(localDateFormatter));
            builder.serializers(new LocalDateTimeSerializer(localDateTimeFormatter));
            builder.deserializers(new LocalDateDeserializer(localDateFormatter));
            builder.deserializers(new LocalDateTimeDeserializer(localDateTimeFormatter));
        };
    }

    /**
     * 请求参数 - 日期格式化转换配置
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        //java.util.Date日期格式
        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        DateFormatter dateFormatter = new DateFormatter(this.webJacksonProps.getDateFormat());
        dateFormatter.setTimeZone(TimeZone.getTimeZone(this.webJacksonProps.getTimeZone()));
        dateRegistrar.setFormatter(dateFormatter);
        dateRegistrar.registerFormatters(registry);

        //Java8+ java.time.*日期格式
        DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
        dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern(this.webJacksonProps.getLocalDateFormat())
                .withZone(ZoneId.of(this.webJacksonProps.getTimeZone())));
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern(this.webJacksonProps.getLocalDateTimeFormat())
                .withZone(ZoneId.of(this.webJacksonProps.getTimeZone())));
        dateTimeRegistrar.registerFormatters(registry);
    }
}
